package com.lcz.customview_watch

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.icu.text.SimpleDateFormat
import android.icu.util.Calendar
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import java.text.DecimalFormat


/**
 * 作者: 刘传政
 *
 * 时间: 2024/4/25 0025 10:05
 *
 * QQ:1052374416
 *
 * 作用:表
 *
 * 注意事项:
 */
class WatchView : View {

    private var _timeTextColor: Int = Color.BLUE
    private var scaleLineColor: Int = context.getColor(R.color.scaleLineColor)
    private var minuteColor: Int = context.getColor(R.color.minuteColor)
    private var hourColor: Int = context.getColor(R.color.hourColor)

    private lateinit var mPaint: Paint
    private lateinit var mTimeTextPaint: TextPaint
    private val mSixtyFormat: DecimalFormat = DecimalFormat("00") // 05 - 60 数字格式器
    val dateFormatter = SimpleDateFormat("HH:mm:ss")
    private var centerX: Float = 0F
    private var centerY: Float = 0F
    private var mScalelineLength: Float = 0F //刻度的长度
    private val mCalendar: Calendar = Calendar.getInstance() // 日期
    var textBound: Rect = Rect()


    /**
     * 时间文字的颜色
     */
    var timeTextColor: Int
        get() = _timeTextColor
        set(value) {
            _timeTextColor = value
            refreshTextPaint()
        }


    constructor(context: Context) : super(context) {
        init(null, 0)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(attrs, 0)
    }

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
        init(attrs, defStyle)
    }

    private fun init(attrs: AttributeSet?, defStyle: Int) {
        // 加载自定义属性 只举个列子，加了一个属性
        val a = context.obtainStyledAttributes(
            attrs, R.styleable.WatchView, defStyle, 0
        )
        _timeTextColor = a.getColor(
            R.styleable.WatchView_timeTextColor,
            timeTextColor
        )

        a.recycle()



        initPaint()
        setBackgroundColor(Color.BLACK)
    }

    private fun initPaint() {
        mPaint = Paint()
        mPaint.flags = Paint.ANTI_ALIAS_FLAG //抗锯齿
        mTimeTextPaint = TextPaint()
        mTimeTextPaint.setColor(timeTextColor)
//        mTimeTextPaint.setTextAlign(Paint.Align.CENTER) //文字居中
        mTimeTextPaint.textSize = 50F
        mTimeTextPaint.flags = Paint.ANTI_ALIAS_FLAG


    }

    private fun refreshTextPaint() {
        mTimeTextPaint.let {
            it.color = timeTextColor
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        centerX = (w / 2).toFloat()
        centerY = (h / 2).toFloat()
        mScalelineLength = w / 35f
    }

    /**
     * 获取宽高的最小值，确定正方形的边长
     *
     */
    private fun getSquareSize(): Int {
        var min = Math.min(width, height) - 10 //-10是为了留点间距
        return min
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        drawScaleLines(canvas)
        drawMinuteText(canvas)
        drawHourText(canvas)
        drawPointers(canvas)
        drawTimeText(canvas)
        postInvalidateDelayed(250) //每隔250毫秒刷新一次，这里不能每1秒刷新，因为绘制消耗一点时间，可能出现用户看到一下跳了两格的现象
    }

    /**
     * 画时间文字
     *
     * @param canvas
     */
    private fun drawTimeText(canvas: Canvas) {
        var timeText = dateFormatter.format(mCalendar)

        canvas.drawText(timeText, centerX - 90, centerY + getSquareSize() / 4, mTimeTextPaint)

    }

    private fun drawPointers(canvas: Canvas) {
        mCalendar.timeInMillis = System.currentTimeMillis() //更新一下时间
        drawHourPointer(canvas)
        drawMinutePointer(canvas)
        drawSecondPointer(canvas)
    }

    /**
     * 画时针
     *
     * @param canvas
     */
    private fun drawHourPointer(canvas: Canvas) {
        val hour = mCalendar.get(Calendar.HOUR)
        val minute = mCalendar.get(Calendar.MINUTE)
        val second = mCalendar.get(Calendar.SECOND)
        mPaint.setColor(hourColor);

        mPaint.setStrokeCap(Paint.Cap.ROUND)

        canvas.save()
        canvas.translate(centerX, centerY)
        // 时针转过的角度
        val jiaodu = (hour + minute / 60f + second / 3600f) * 360 / 12f
        val hudu = jiaodu * 2 * Math.PI / 360
        // 绘制指针细的一端

        mPaint.setStrokeWidth(10f)
        var smallRadius = getSquareSize() / 2 * 2 / 3
        canvas.drawLine(
            0f,
            0F,
            (smallRadius * Math.sin(hudu)).toFloat(),
            -(smallRadius * Math.cos(hudu)).toFloat(),
            mPaint
        )
        // 绘制指针粗的一端
        var bigRadius = getSquareSize() / 2 * 2 / 3
        var padding = 50f
        mPaint.setStrokeWidth(20f)
        canvas.drawLine(
            0f + (padding * Math.sin(hudu)).toFloat(),
            0F - (padding * Math.cos(hudu)).toFloat(),
            (bigRadius * Math.sin(hudu)).toFloat(),
            -(bigRadius * Math.cos(hudu)).toFloat(),
            mPaint
        )
        // 绘制圆心点
        canvas.drawCircle(0f, 0f, 20f, mPaint)
        canvas.restore()
    }

    /**
     * 画分针
     *
     * @param canvas
     */
    private fun drawMinutePointer(canvas: Canvas) {
        val hour = mCalendar.get(Calendar.HOUR)
        val minute = mCalendar.get(Calendar.MINUTE)
        val second = mCalendar.get(Calendar.SECOND)
        mPaint.setColor(minuteColor);

        mPaint.setStrokeCap(Paint.Cap.ROUND)

        canvas.save()
        canvas.translate(centerX, centerY)
        // 分针转过的角度
        val jiaodu = (minute + second / 60f) * 360 / 60f
        val hudu = jiaodu * 2 * Math.PI / 360
        // 绘制指针细的一端

        mPaint.setStrokeWidth(10f)
        var smallRadius = getSquareSize() / 2 - mScalelineLength * 1.5
        canvas.drawLine(
            0f,
            0F,
            (smallRadius * Math.sin(hudu)).toFloat(),
            -(smallRadius * Math.cos(hudu)).toFloat(),
            mPaint
        )
        // 绘制指针粗的一端
        var bigRadius = getSquareSize() / 2 - mScalelineLength * 1.5
        var padding = 50f
        mPaint.setStrokeWidth(20f)
        canvas.drawLine(
            0f + (padding * Math.sin(hudu)).toFloat(),
            0F - (padding * Math.cos(hudu)).toFloat(),
            (bigRadius * Math.sin(hudu)).toFloat(),
            -(bigRadius * Math.cos(hudu)).toFloat(),
            mPaint
        )
        // 绘制圆心点
        canvas.drawCircle(0f, 0f, 20f, mPaint)
        canvas.restore()
    }

    /**
     * 画秒针
     *
     * @param canvas
     */
    private fun drawSecondPointer(canvas: Canvas) {
        val hour = mCalendar.get(Calendar.HOUR)
        val minute = mCalendar.get(Calendar.MINUTE)
        val second = mCalendar.get(Calendar.SECOND)
        mPaint.setColor(Color.RED)

        mPaint.setStrokeCap(Paint.Cap.ROUND)

        canvas.save()
        canvas.translate(centerX, centerY)
        // 分针转过的角度
        val jiaodu = (second) * 360 / 60f
        val hudu = jiaodu * 2 * Math.PI / 360

        mPaint.setStrokeWidth(5f)
        var overLineLength = getSquareSize() / 15//超出的那部分小短线
        var radius = getSquareSize() / 2 - mScalelineLength * 1
        // 绘制超出的小短线指针
        canvas.drawLine(
            0f,
            0F,
            0 - (overLineLength * Math.sin(hudu)).toFloat(),
            0 + (overLineLength * Math.cos(hudu)).toFloat(),
            mPaint
        )
        // 绘制长指针
        var padding = 50f
        canvas.drawLine(0f, 0F, (radius * Math.sin(hudu)).toFloat(), -(radius * Math.cos(hudu)).toFloat(), mPaint)
        // 绘制圆心点
        canvas.drawCircle(0f, 0f, 15f, mPaint)
        mPaint.setColor(Color.BLACK)
        canvas.drawCircle(0f, 0f, 10f, mPaint)
        canvas.restore()
    }

    /**
     * 画刻度线
     *
     * @param canvas
     */
    private fun drawScaleLines(canvas: Canvas) {
        mPaint.strokeWidth = 5f
        mPaint.strokeCap = Paint.Cap.ROUND
        mPaint.setColor(scaleLineColor)
        canvas.save()
        canvas.translate(centerX, centerY)
        for (i in 0..60) {

            if (i % 5 != 0) {
                canvas.drawLine(
                    0f,
                    (-getSquareSize() / 2).toFloat(),
                    0f,
                    (-getSquareSize() / 2).toFloat() + mScalelineLength,
                    mPaint
                )
            }
            canvas.rotate(6F, 0F, 0F)
        }
        canvas.restore()
    }

    /**
     * 画分钟的数字
     *
     * @param canvas
     */
    private fun drawMinuteText(canvas: Canvas) {
        mPaint.color = minuteColor
        mPaint.textSize = 30F
        mPaint.isFakeBoldText = true
        var radius = getSquareSize() / 2 - mScalelineLength / 2
        var x: Float
        var y: Float
        for (i in 5..60 step 5) {
            //格式化数字
            var format = mSixtyFormat.format(i)
            mPaint.getTextBounds(format, 0, format.length, textBound);
            //计算出角度
            var jiaodu = 360 / 60 * i
            //将角度换算成弧度 根据2π=360度
            var hudu = jiaodu * 2 * Math.PI / 360
            //三角函数算x,y  文字是以左下角为起点进行绘制的，为了保证文字的中心点位于圆圈上所以得进行位移
            x = (centerX + radius * Math.sin(hudu) - textBound.width() / 2).toFloat()
            y = (centerY - radius * Math.cos(hudu) + textBound.height() / 2).toFloat()
            canvas.drawText(format, x, y, mPaint)
        }
    }

    /**
     * 画小时的数字
     *
     * @param canvas
     */
    private fun drawHourText(canvas: Canvas) {
        mPaint.color = hourColor
        mPaint.textSize = 70F
        mPaint.isFakeBoldText = true
        var radius = getSquareSize() / 2 - mScalelineLength * 3
        var x: Float
        var y: Float
        for (i in 5..60 step 5) {
            //格式化数字
            var format = "" + i / 5
            mPaint.getTextBounds(format, 0, format.length, textBound);
            //计算出角度
            var jiaodu = 360 / 60 * i
            //将角度换算成弧度 根据2π=360度
            var hudu = jiaodu * 2 * Math.PI / 360
            //三角函数算x,y  文字是以左下角为起点进行绘制的，为了保证文字的中心点位于圆圈上所以得进行位移
            x = (centerX + radius * Math.sin(hudu) - textBound.width() / 2).toFloat()
            y = (centerY - radius * Math.cos(hudu) + textBound.height() / 2).toFloat()
            canvas.drawText(format, x, y, mPaint)
        }
    }
}